
#include "stdafx.h"
#include "SceneViewTreeCtrl.h"
#include "MainFrm.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CSceneViewTreeCtrl

CSceneViewTreeCtrl::CSceneViewTreeCtrl()
{
 m_bLDragging = false;
}

CSceneViewTreeCtrl::~CSceneViewTreeCtrl()
{
}

BEGIN_MESSAGE_MAP(CSceneViewTreeCtrl, CTreeCtrl)
  	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONUP()
	ON_WM_KEYDOWN()
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSceneViewTreeCtrl message handlers

BOOL CSceneViewTreeCtrl::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
	BOOL bRes = CTreeCtrl::OnNotify(wParam, lParam, pResult);

	NMHDR* pNMHDR = (NMHDR*)lParam;
	ASSERT(pNMHDR != NULL);

	if (pNMHDR && pNMHDR->code == TTN_SHOW && GetToolTips() != NULL)
	{
		GetToolTips()->SetWindowPos(&wndTop, -1, -1, -1, -1, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);
	}
	return bRes;
}

void CSceneViewTreeCtrl::OnMouseMove(UINT nFlags, CPoint point) 
{
	HTREEITEM hitem;
	UINT flags;

	if (m_bLDragging)
	{
		POINT pt = point;
		ClientToScreen( &pt );
		CImageList::DragMove(pt);
		if ((hitem = HitTest(point, &flags)) != NULL)
		{
			CImageList::DragShowNolock(FALSE);
			m_hitemDrop = GetDropTarget(hitem);
			SelectDropTarget(m_hitemDrop);
			CImageList::DragShowNolock(TRUE);
		}
		else
			m_hitemDrop = NULL;
		if (m_hitemDrop)
			SetCursor(m_dropCursor);
		else
			SetCursor(m_noDropCursor);
	}

	CTreeCtrl::OnMouseMove(nFlags, point);
}

void CSceneViewTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point) 
{
	CTreeCtrl::OnLButtonUp(nFlags, point);

	if (m_bLDragging)
	{
		m_bLDragging = FALSE;
		CImageList::DragLeave(this);
		CImageList::EndDrag();
		ReleaseCapture();

		delete m_pDragImage;

		// Remove drop target highlighting
		SelectDropTarget(NULL);

		if( m_hitemDrag == m_hitemDrop || m_hitemDrop == NULL)
			return;

		// If Drag item is an ancestor of Drop item then return
		HTREEITEM htiParent = m_hitemDrop;
		while( (htiParent = GetParentItem( htiParent )) != NULL )
		{
			if( htiParent == m_hitemDrag ) return;
		}

		Expand( m_hitemDrop, TVE_EXPAND ) ;

		HTREEITEM htiNew = CopyBranch(m_hitemDrag, m_hitemDrop, TVI_LAST );

        String sourceName = ConvertToApoString(GetItemText(m_hitemDrag));
        String destName = ConvertToApoString(GetItemText(m_hitemDrop));

        CBaseEditor *source = ClientRoot::getInstance().FindObject(sourceName); 
        CBaseEditor *dest = ClientRoot::getInstance().FindObject(destName);

        source->ChangeParent(dest, true);
		DeleteItem(m_hitemDrag);
        source->SetLocked(dest->GetLocked(), true);

		SelectItem( htiNew );
	}
}

void CSceneViewTreeCtrl::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

	// TODO: Add your control notification handler code here
	*pResult = 0;

	m_hitemDrag = pNMTreeView->itemNew.hItem;
	m_hitemDrop = NULL;
	SelectItem( m_hitemDrag );
	if (!IsDropSource(m_hitemDrag))
		return;

	// get the image list for dragging 
	m_pDragImage = CreateDragImage(m_hitemDrag);
	// CreateDragImage() returns NULL if no image list 
	// associated with the tree view control 
	if( !m_pDragImage )
		return;

	m_bLDragging = TRUE;
	m_pDragImage->BeginDrag(0, CPoint(15, 15));
	POINT pt = pNMTreeView->ptDrag;
	ClientToScreen( &pt );
	m_pDragImage->DragEnter(NULL, pt);
	SetCapture();
}

HTREEITEM CSceneViewTreeCtrl::CopyBranch( HTREEITEM htiBranch, HTREEITEM htiNewParent, HTREEITEM htiAfter)
{
        HTREEITEM hChild;

        HTREEITEM hNewItem = CopyItem( htiBranch, htiNewParent, htiAfter );
        hChild = GetChildItem(htiBranch);
        while( hChild != NULL)
        {
                // recursively transfer all the items
                CopyBranch(hChild, hNewItem);  
                hChild = GetNextSiblingItem( hChild );
        }
        return hNewItem;
}

HTREEITEM CSceneViewTreeCtrl::CopyItem( HTREEITEM hItem, HTREEITEM htiNewParent, HTREEITEM htiAfter )
{
        TV_INSERTSTRUCT         tvstruct;
        HTREEITEM                       hNewItem;
        CString                         sText;

        // get information of the source item
        tvstruct.item.hItem = hItem;
        tvstruct.item.mask = TVIF_CHILDREN | TVIF_HANDLE | 
                                TVIF_IMAGE | TVIF_SELECTEDIMAGE;
        GetItem(&tvstruct.item);  
        sText = GetItemText( hItem );
        
        tvstruct.item.cchTextMax = sText.GetLength();
        tvstruct.item.pszText = sText.LockBuffer();

        // Insert the item at proper location
        tvstruct.hParent = htiNewParent;
        tvstruct.hInsertAfter = htiAfter;
        tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
        hNewItem = InsertItem(&tvstruct);
        sText.ReleaseBuffer();

        // Now copy item data and item state.
        SetItemData( hNewItem, GetItemData( hItem ));
        SetItemState( hNewItem, GetItemState( hItem, TVIS_STATEIMAGEMASK ), 
                                                        TVIS_STATEIMAGEMASK );
        return hNewItem;
}

BOOL CSceneViewTreeCtrl::IsDropSource(HTREEITEM hItem)
{
  String sText = ConvertToApoString(GetItemText( hItem )); 
  CBaseEditor *ed = ClientRoot::getInstance().FindObject(sText);

  if(!ed) return false;

  return ed->Supports(CAN_DRAG) && !ed->GetLocked();
}

HTREEITEM CSceneViewTreeCtrl::GetDropTarget(HTREEITEM hItem)
{
	// inhibit drop on the drop source or its parent
	if (hItem == m_hitemDrag || hItem == GetParentItem(m_hitemDrag))
		return NULL;
   
  String sText = ConvertToApoString(GetItemText( hItem )); 
  CBaseEditor *ed = ClientRoot::getInstance().FindObject(sText);

  if(!ed) return false;

  if(ed->Supports(CAN_DROP))
	return hItem;
  else
	return NULL;
}

BOOL CSceneViewTreeCtrl::PreTranslateMessage(MSG* pMsg)
{
//   if(pMsg->message == WM_KEYDOWN)
//   {
//     CChildView *view = &(((CMainFrame *)AfxGetApp()->GetMainWnd())->getChildView());
// 	CViewportEditor *ovp = gClientRootGetViewport();
//     if(pMsg->wParam == VK_DELETE) 
// 	{
// 	  if(ovp)
//           ovp->DeleteSelectedObject();
// 	  view->SetFocus();
// 	  return TRUE;
// 	}
// 	if(pMsg->wParam == 0x46) 
// 	{
// 	  if(ovp)
//           ovp->FocusSelectedObject();
// 	  view->SetFocus();
// 	  return TRUE;
// 	}
//   }
//   return CTreeCtrl::PreTranslateMessage(pMsg);
	return NULL;
}


void CSceneViewTreeCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
  CTreeCtrl::OnKeyDown(nChar,nRepCnt,nFlags);
}

void CSceneViewTreeCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMLISTVIEW pnm = (LPNMLISTVIEW)pNMHDR;

    if (pnm->hdr.code == NM_CUSTOMDRAW)
    {
        *pResult = 0;

        LPNMTVCUSTOMDRAW lplvcd = (LPNMTVCUSTOMDRAW)pNMHDR;
        ASSERT(m_hWnd == pnm->hdr.hwndFrom);

        switch(lplvcd->nmcd.dwDrawStage) 
        {
        case CDDS_PREPAINT:
             *pResult = CDRF_NOTIFYITEMDRAW;
             return;

        case CDDS_ITEMPREPAINT:
             *pResult = CDRF_DODEFAULT;

             TCHAR szFace[LF_FACESIZE];
             HTREEITEM hItem = (HTREEITEM) lplvcd->nmcd.dwItemSpec;
             TVITEM tvi = { 0 };
             tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT;
             tvi.hItem = hItem;
             tvi.pszText = szFace;
             tvi.cchTextMax = sizeof(szFace)/sizeof(TCHAR);
             GetItem(&tvi);
             if (tvi.lParam) 
             {
                 lplvcd->clrText = tvi.lParam;
             }
        }
    }
}